﻿package org.abc.utils
{
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;

	/**
	 * @author aishi
	 * 显示对象工具类,替换，自动缩放居中显示，获取/删除/隐藏/显示对象
	 */
	public class InstanceUtil
	{
		/**
		 * 替换显示对象并且复制属性
		 * @param	oldDis		旧显示对象
		 * @param	newDis		新显示对象
		 */
		public static function replaceDisplayObject(oldDis:DisplayObject, newDis:DisplayObject):void
		{
			//复制源显示对象的各种显示属性到目标显示对象
			newDis.transform=oldDis.transform;
			if (newDis is Sprite && oldDis is Sprite)
			{
				Sprite(newDis).buttonMode=Sprite(oldDis).buttonMode;
			}

			var parentContainer:DisplayObjectContainer=oldDis.parent;

			if (!parentContainer)
			{
				trace("容器未定义！");
				return;
			}

			var childIndex:int=parentContainer.getChildIndex(oldDis);
			parentContainer.removeChildAt(childIndex);
			parentContainer.addChildAt(newDis, childIndex);

		}

		/**
		 * 对象大小自动匹配显示区域并居中显示
		 * @param container 显示区域
		 * @param obj 对象
		 * @param isfull 是否满屏
		 * @return
		 *
		 */
		public static function autoSize(container:DisplayObjectContainer, obj:DisplayObject, isfull:Boolean=false):Rectangle
		{
			if (!Boolean(container))
			{
				trace("autoSize容器未定义！");
				return null;
			}
			if (!Boolean(obj))
			{
				trace("autoSize对象未定义！");
				return null;
			}
			var min:Number=Math.min(container.width / obj.width, container.height / obj.height)
			min=isfull ? min : (min > 1 ? 1 : min)
			//获取对象中心点偏移量
			var rect:Rectangle=getoffset(obj)
			obj.scaleX=obj.scaleY=min
			rect=getoffset(obj)
			obj.x=(container.width - obj.width) / 2 - rect.x
			obj.y=(container.height - obj.height) / 2 - rect.y

			//如果背景容器内容为空则
			if (min == 0)
			{
				obj.scaleX=obj.scaleY=1
				rect=getoffset(obj)
				obj.x=obj.width / 2 - rect.x
				obj.y=obj.height / 2 - rect.y
			}
			container.addChild(obj)
			return new Rectangle(obj.x + rect.x, obj.y + rect.y, obj.width, obj.height);
		}

		/**
		 * 获取对象的中心点相对左顶点的偏移量
		 * @param obj
		 * @return
		 *
		 */
		public static function getoffset(obj:DisplayObject):Rectangle
		{

			var container:Sprite=obj.parent as Sprite

			//获取对象中心点偏移量
			var mc:Sprite=new Sprite()
			obj.visible=false
			mc.addChild(obj)

			var rect:Rectangle=obj.getBounds(mc)
			mc.removeChild(obj)
			obj.visible=true

			if (container != null)
			{
				container.addChild(obj)
			}

			return rect;

		}

		/**
		 * 获取指定对象实例所有子对象实例集合
		 * @param container 操作对象实例
		 * @return Array
		 *
		 */
		public static function getAllObjs(container:Sprite):Array
		{
			if (!container)
			{
				trace("容器未定义！");
				return [];
			}
			var objs:Array=[];
			for (var i:Number=0; i < container.numChildren; i++)
			{
				var item:DisplayObject=container.getChildAt(i)
				objs.push(item);
			}
			return objs;
		}

		/**
		 * 删除指定对象
		 * @param obj 要删除的对象实例
		 * @return
		 *
		 */
		public static function cleanObj(obj:DisplayObject):void
		{

			if (!obj)
			{
				trace("容器未定义！");
				return;
			}
			if (!obj.parent)
			{
				//	trace("对象不在场景中！"); 
				return;
			}
			obj.parent.removeChild(obj)
		}

		/**
		 * 删除指定类型对象实例集合
		 * @param type 类对象
		 * @param container 操作对象实例
		 *
		 */
		public static function cleanObjByType(type:Class, container:Sprite):void
		{
			getAllObjs(container).forEach(function(element:*, index:int, arr:Array):void
			{
				if (element is type)
				{
					container.removeChild(element);
				}
			});
		}

		/**
		 * 清空指定对象
		 * @param container 操作对象实例
		 * @return
		 *
		 */
		public static function cleanAllObjs(container:Sprite):void
		{
			getAllObjs(container).forEach(function(element:*, index:int, arr:Array):void
			{
				container.removeChild(element);
			});

		}

		/**
		 * 获取指定类型对象实例集合
		 * @param type 类对象
		 * @param container 操作对象实例
		 * @return Array
		 *
		 */
		public static function getObjsByType(type:Class, container:Sprite):Array
		{
			return getAllObjs(container).filter(function(element:*, index:int, arr:Array):*
			{
				return element is type;
			});
		}

		/**
		 * 删除除指定类型外的其他类型对象实例集合
		 * @param type 类对象
		 * @param container 操作对象实例
		 * @return
		 *
		 */
		public static function cleanAllBesideType(type:Class, container:Sprite):void
		{
			getAllObjs(container).forEach(function(element:*, index:int, arr:Array):void
			{
				if (!(element is type))
				{
					container.removeChild(element)
				}
			})
		}

		/**
		 * 获取除指定类型外的其他类型集合
		 * @param type 类对象
		 * @param container 操作对象实例
		 * @return Array
		 *
		 */
		public static function getAllBesideType(type:Class, container:Sprite):Array
		{
			return getAllObjs(container).filter(function(element:*, index:int, arr:Array):*
			{
				return !(element is type)
			})
		}

		/**
		 * 显示指定对象实例中所有子对象实例集合
		 * @param container 操作对象实例
		 * @return
		 *
		 */
		public static function showAllObjs(container:Sprite):void
		{
			getAllObjs(container).forEach(function(element:*, index:int, arr:Array):void
			{
				element.visible=true
			})
		}

		/**
		 * 隐藏指定对象中所有子对象
		 * @param container 操作对象实例
		 * @return
		 *
		 */
		public static function hideAllObjs(container:Sprite):void
		{
			getAllObjs(container).forEach(function(element:*, index:int, arr:Array):void
			{
				element.visible=false
			})
		}

		/**
		 * 显示指定类型对象结合
		 * @param type 类对象
		 * @param container 操作对象实例
		 * @return
		 *
		 */
		public static function showObjsByType(type:Class, container:Sprite):void
		{
			getAllObjs(container).forEach(function(element:*, index:int, arr:Array):void
			{
				if (element is type)
					element.visible=true
			})
		}

		/**
		 * 隐藏指定类型对象结合
		 * @param type 类对象
		 * @param container 操作对象实例
		 * @return
		 *
		 */
		public static function hideObjsByType(type:Class, container:Sprite):void
		{
			getAllObjs(container).forEach(function(element:*, index:int, arr:Array):void
			{
				if (element is type)
					element.visible=false
			})
		}

		/**
		 * 隐藏除指定类型外的其他类型结合
		 * @param type 类对象
		 * @param container 操作对象实例
		 * @return
		 *
		 */
		public static function hideObjsBesideType(type:Class, container:Sprite):void
		{
			getAllObjs(container).forEach(function(element:*, index:int, arr:Array):void
			{
				if (!(element is type))
					element.visible=false
			})
		}

		/**
		 * 显示除指定类型外的其他类型结合
		 * @param type 类对象
		 * @param container 操作对象实例
		 * @return
		 *
		 */
		public static function showObjsBesideType(type:Class, container:Sprite):void
		{
			getAllObjs(container).forEach(function(element:*, index:int, arr:Array):void
			{
				if (!(element is type))
					element.visible=true
			})
		}
		/**
		 * 获取显示对象在祖先容器中的位置
		 * 判断祖先容器，主要是通过判断parent是否是MovieClip，stage和sprite不在考虑范围
		 * 
		 * @author	Mr.zheng
		 * @param	dp		目标显示对象
		 * @param	depth	目标对象在祖先中的深度，祖先深度为0
		 * @return 
		 * 
		 */
		public static function getPosInForfarther(dp:DisplayObject,depth:int):Point{
			var p:Point=new Point();
			var theParent:DisplayObjectContainer=dp.parent;
			if(depth<=0){
				p.x=theParent.x;
				p.y=theParent.y;
				return p;
			}
			//需要的值是在祖先中的坐标，因此，祖先的坐标不用取，这里-1
			for (var i:int = 0; i < depth-1; i++) 
			{
				p.x+=theParent.x;
				p.y+=theParent.y;
				theParent=theParent.parent;
			}
			return p;
			
		}
		/**
		 * 祖先的matrix集合
		 * @param	dp
		 * @param	depth
		 */
		static public function getMatrixs(dp:DisplayObject, depth:int):Matrix 
		{
			var mt:Matrix = dp.transform.matrix;
			var theParent:DisplayObjectContainer = dp.parent;
			for (var i:int = 0; i < depth; i++) 
			{
				mt.concat(theParent.transform.matrix);
				theParent=theParent.parent;
			}
			return mt;
		}
	}
}
